package com.atguigu.Threads;

/**
 * 例子：线程1和线程2交替输出1到100的奇数和偶数
 * 解决方案：
 *      1.wait()是当前线程进入阻塞状态，并释放对当前CPU的执行权
 *      2.notify()（notifyall)唤醒当前wait()的进程
 *特需说明：线程操作的wait()、notify()、notifyAll()方法(定义在object类中）只能在同步控制方法或同步控制块内调用。
 * 如果在非同步控制方法或控制块里调用，程序能通过编译，但运行的时候，将得到 IllegalMonitorStateException 异常，
 * 并伴随着一些含糊信息，比如 ‘当前线程不是拥有者’。其实异常的含义是 调用wait()、notify()、notifyAll()的任务在调用这些方法前必须 ‘拥有’（获取）对象的锁。
 *
 * wait()和sleep()
 *  相同点：都可以使线程进入阻塞状态
 *  不同的：
 *      1.两个方法声明的位置不同，Thread类中声明sleep(),Object类中声明wait()
 *      2.调用的要求不同，sleep()可以在任何需要的场景下调用，wait()必须在同步代码块或方法中使用
 *      3.sleep()后线程进入休眠状态，不会释放对CPU的执行权，wait()后进入阻塞状态，释放对CPU的执行权，notify()
 * @author xiaoqi
 * @data 2021/04/07 16:45
 */

//定义一个报号的类
class NumPrint extends Thread{
    //设置为静态的
    private static int number = 1;

    @Override
    public void run() {
        while(true){
            //使用主线程中的类的字节码文件保证线程安全
            synchronized (ThreadConnucation.class) {
                //唤醒线程
                ThreadConnucation.class.notify();
                if(this.number <= 100){
                    System.out.println(Thread.currentThread().getName() + "-" + this.number);
                    this.number++;
                }else {
                    break;
                }

                try {
                    ThreadConnucation.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class ThreadConnucation {
    public static void main(String[] args) {
        //创建两个对象
        NumPrint numPrint1 = new NumPrint();
        NumPrint numPrint2 = new NumPrint();
        //设置线程名
        numPrint1.setName("线程1");
        numPrint2.setName("线程2");
        //执行线程
        numPrint1.start();
        numPrint2.start();

    }
}
